#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include <time.h>




int Random (int Min, int Max)
{
return (Min + (rand () % (Max-Min+1)));
}

 int  Min(int a,int b)
 {
     return (a<=b?a:b);
 }




int GetDimxLabyrinthe (const labyrinthe *Laby)
{
    return Laby->dimx;
}
int GetDimyLabyrinthe (const labyrinthe *Laby)
{
    return Laby->dimy;
}

caseMat* GetcaseMatLabyrinthe (const labyrinthe* Laby, const int *x, const int *y)
{
    return (&Laby->Mat[*x][*y]);
}





void InitLabyrinthe (labyrinthe * Laby, const int *dimx,  const int *dimy)
{

int cpt=0;
int i,j;


Laby->dimx=*dimx;
Laby->dimy=*dimy;


Laby->Mat=(caseMat**)malloc(sizeof(caseMat*)*(Laby->dimx));

for (i=0; i<Laby->dimx; i++)
{
    Laby->Mat[i]=(caseMat*)malloc(sizeof(caseMat)*(Laby->dimy));
}



for (i=0;i<Laby->dimx;i++)
{
for (j=0; j<Laby->dimy; j++)
{
  InitCase(&Laby->Mat[j][i],&cpt,&Laby->dimx,&Laby->dimy);

  cpt++;
}
}

}




void afficheLabyrinthe (labyrinthe *Laby, const int *dimx,const int *dimy) // affiche en mode texteun labyrinthe
{
    int i,j;
    for (i=0;i<Laby->dimx;i++)
    {
        for (j=0;j<Laby->dimy;j++)
        {
            afficheCase(&Laby->Mat[j][i]);
        }
}
}

bool fini (labyrinthe *Laby) // cette fonction revoie un bool qui nous informe si les identifiants de toutes les cases sont à 0 --> fin de la construction du labyrinthe
{
    bool fin=true;
    int i=0, j;
    int ident=GetIdentCase(&Laby->Mat[0][0]);
    while (fin &&  i<Laby->dimx)
    {
        for (j=0;j<Laby->dimy;j++)
        {
            if (GetIdentCase(&Laby->Mat[i][j])!=ident)
            {
                fin=false;
            }

        }
      i++;
       }
return fin;
 }



bool passageExist (const caseMat *Case,  const int *direct )
{
   return GetH_B_G_D(Case,direct);
}


void verifChemin(labyrinthe *Laby,int x,  int y, const int *ident, const int *identChemin)
{


     if (GetIdentCase(&Laby->Mat[x][y])==*identChemin)
     {
       setChangeIdent(&Laby->Mat[x][y],ident);

       if (y!=0  && GetIdentCase(&Laby->Mat[x][y-1])==*identChemin)
       {

           verifChemin (Laby, x, y-1,ident,identChemin);
           }
       if (x!=Laby->dimx-1  && GetIdentCase(&Laby->Mat[x+1][y])==*identChemin)
       {
           verifChemin (Laby, x+1, y,ident,identChemin);
           }
       if (y!=Laby->dimy-1 && GetIdentCase(&Laby->Mat[x][y+1])==*identChemin)
       {
           verifChemin (Laby, x, y+1,ident,identChemin);
           }


       if (x!=0 && GetIdentCase(&Laby->Mat[x-1][y])==*identChemin)
       {
           verifChemin (Laby, x-1, y,ident,identChemin);
           }




}
}




// avant la fonction je fais get ident
int  murAleatoir(int xAlea, int yAlea, int dimx, int dimy)
{
int murAlea[4];

if (yAlea==0)
{

  if (xAlea==0)
    {
        murAlea[0]=2;
        murAlea[1]=3;
        return murAlea[rand()%2];

      }
  else if (xAlea==dimx-1)
    {
        murAlea[0]=3;
        murAlea[1]=4;
        return  murAlea[rand()%2];
        }

    else
      {
        murAlea[0]=1;
        murAlea[1]=2;
        murAlea[2]=4;
        return  murAlea[rand()%3];
        murAlea[0]=2;
        murAlea[1]=3;
        murAlea[2]=4;
        return  murAlea[rand()%3];
      }
}
else if (yAlea==dimy-1)
{



  if (xAlea==0)
    {
        murAlea[0]=2;
        murAlea[1]=1;
        return  murAlea[rand()%2];
      }
  else if (xAlea==dimx-1)
    {
        murAlea[0]=1;
        murAlea[1]=4;
        return  murAlea[rand()%2];
       }

    else
      {
        murAlea[0]=1;
        murAlea[1]=2;
        murAlea[2]=4;
        return  murAlea[rand()%3];

        }
}
else
{
    if (xAlea==0)
    {
        murAlea[0]=1;
        murAlea[1]=2;
        murAlea[2]=3;
        return  murAlea[rand()%3];
    }
    else if (xAlea==dimx-1)
    {
        murAlea[0]=1;
        murAlea[1]=3;
        murAlea[2]=4;
        return  murAlea[rand()%3];
        }
    else
    {
        murAlea[0]=1;
        murAlea[1]=2;
        murAlea[2]=3;
        murAlea[3]=4;
        return  murAlea[rand()%3];
    }
}

}


}




InitLabyrinthe(Laby, dimx, dimy);

srand(time(NULL));

void genererLabyrinthe(labyrinthe *Laby, const int *dimx,const int *dimy)
{


int max1,max2,xAlea,yAlea,i;
int mur,  identCase, identChemin,cpt=1;

InitLabyrinthe(Laby, dimx, dimy);

srand(time(NULL));

max1=*dimx;
max2=*dimy;

int maxx=(*dimx)*(*dimy);

while (cpt<maxx)
{
//for (i=0;  i<12; i++)
//{

xAlea=rand()%max1;
yAlea=rand()%max2;
/*
max1=4;
setChangeIdent(&Laby->Mat[0][0],&max1);
setChangeIdent(&Laby->Mat[1][0],&max1);
setChangeIdent(&Laby->Mat[0][1],&max1);
xAlea=2;
yAlea=0;
mur=4;
*/

mur=murAleatoir(xAlea, yAlea,Laby->dimx, Laby->dimy);

printf ("\n\n***%d***%d-->%d",xAlea, yAlea, mur);

identCase=GetIdentCase(&Laby->Mat[xAlea][yAlea]);


switch (mur)
{
    case 1:
    identChemin=GetIdentCase(&Laby->Mat[xAlea][yAlea-1]);
    if (GetIdentCase(&Laby->Mat[xAlea][yAlea-1])!=GetIdentCase(&Laby->Mat[xAlea][yAlea]))
    {
        /*if (GetIdentCase(&Laby->Mat[xAlea][yAlea])> GetIdentCase(&Laby->Mat[xAlea][yAlea-1]))
        {

          setChangeIdent (&Laby->Mat[xAlea][yAlea],&identChemin);

            }
        else
        {*/

          verifChemin(Laby,xAlea, yAlea-1,&identCase,&identChemin);

          setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea],mur,true);

          setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea-1],3,true);
         cpt=cpt+1;

          verifChemin(Laby,xAlea, yAlea-1,&identCase,&identChemin);

         //}
        }
    break;

    case 2:
    identChemin=GetIdentCase(&Laby->Mat[xAlea+1][yAlea]);
    if (GetIdentCase(&Laby->Mat[xAlea+1][yAlea])!=GetIdentCase(&Laby->Mat[xAlea][yAlea]))
    {
       /* if (GetIdentCase(&Laby->Mat[xAlea][yAlea])> GetIdentCase(&Laby->Mat[xAlea+1][yAlea]))
        {

          setChangeIdent (&Laby->Mat[xAlea][yAlea],&identChemin);
            }
        else
        {
*/
          setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea],mur,true);
          setOuvrirFermerCase(&Laby->Mat[xAlea+1][yAlea],4,true);
          verifChemin(Laby,xAlea+1, yAlea,&identCase, &identChemin);
        cpt=cpt+1;

     //    }
        }
    break;
    case 3:
    identChemin=GetIdentCase(&Laby->Mat[xAlea][yAlea+1]);
   if (GetIdentCase(&Laby->Mat[xAlea][yAlea+1])!=GetIdentCase(&Laby->Mat[xAlea][yAlea]))
    {
  /*      if (GetIdentCase(&Laby->Mat[xAlea][yAlea])> GetIdentCase(&Laby->Mat[xAlea][yAlea+1]))
        {

          setChangeIdent (&Laby->Mat[xAlea][yAlea],&identChemin);
            }
        else
        {
*/
          setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea],mur,true);
          setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea+1],1,true);
          verifChemin(Laby,xAlea, yAlea+1,&identCase, &identChemin);
                   cpt=cpt+1;

     //    }
        }

          setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea],mur,true);
          setOuvrirFermerCase(&Laby->Mat[xAlea-1][yAlea],2,true);
          verifChemin(Laby,xAlea-1, yAlea,&identCase, &identChemin);
          cpt=cpt+1;

    break;
    case 4:
    identChemin=GetIdentCase(&Laby->Mat[xAlea-1][yAlea]);
    if (GetIdentCase(&Laby->Mat[xAlea-1][yAlea])!=GetIdentCase(&Laby->Mat[xAlea][yAlea]))
    {
    /*    if (GetIdentCase(&Laby->Mat[xAlea][yAlea])> GetIdentCase(&Laby->Mat[xAlea-1][yAlea]))
        {

          setChangeIdent (&Laby->Mat[xAlea][yAlea],&identChemin);
            }
        else
        {
*/        setOuvrirFermerCase(&Laby->Mat[xAlea][yAlea],mur,true);
          setOuvrirFermerCase(&Laby->Mat[xAlea-1][yAlea],2,true);
          verifChemin(Laby,xAlea-1, yAlea,&identCase, &identChemin);
          cpt=cpt+1;

   //      }
        }
    break;

    }

}

}


bool existeSeulePassage(labyrinthe *Laby, const int *x, const int *y)
{
    int cpt=0, direct;



